package com.platform.common.authentication.stateless;

import com.platform.common.authentication.service.AuthUserTokenService;
import com.platform.common.authentication.service.AuthenticationService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @description: 无状态认证Realm
 * @author: WangYang
 * @date: 2017-09-28 14:34
 */
@Slf4j
public class StatelessRealm extends AuthorizingRealm {

    @Autowired
    private AuthUserTokenService authUserTokenService;

    @Autowired
    private AuthenticationService authenticationService;

    @Override
    public boolean supports(AuthenticationToken token) {
        //仅支持StatelessToken类型的Token
        return token instanceof StatelessToken;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String id = (String) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        try {
            authorizationInfo.setRoles(authenticationService.getRoles(id));
            authorizationInfo.setStringPermissions(authenticationService.getPermissions(id));
        } catch (Exception e) {
            log.error("获取角色权限列表出错！id：{} exception：{}", id, e);
        }
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        StatelessToken statelessToken = (StatelessToken) token;
        String id = statelessToken.getId();
        // 根据用户名获取token
        String accessToken = getAccessToken(id);
        // 进行客户端消息摘要和服务器端消息摘要的匹配
        return new SimpleAuthenticationInfo(id, accessToken, getName());
    }

    /**
     * 根据唯一ID获取用户访问凭证
     *
     * @param id 唯一ID
     * @return
     */
    private String getAccessToken(String id) {
        try {
            return authUserTokenService.getAccessToken(id);
        } catch (Exception e) {
            log.error("获取用户访问token出错！id：{} exception：{}", id, e);
        }
        return "";
    }
}
